package org.ntu.rtsearch.store;

import java.io.IOException;

public class RAMOutputStream extends OutputStream {

	private RAMFile file;
	
	private int pointer = 0;	// same as bufferStart
	
	public RAMOutputStream() {
		this(new RAMFile());
	}
	
	public RAMOutputStream(RAMFile file) {
		this.file = file;
	}
	
	/**
	 * copy the file content to the output
	 * @param out
	 * @throws IOException 
	 */
	public void writeTo(OutputStream out) throws IOException {
		flush();
		final long end = file.length;
		long pos = 0;
		int bufferIdx = 0;
		while(pos < end) {
			int length = Math.min(BUFFER_SIZE, (int) (end - pos));
			out.writeBytes(file.getBuffer(bufferIdx++), length);
			pos += length;
		}
	}
	
	/**
	 * flush the buffer, len <= BUFFER_SIZE
	 */
	@Override
	protected void flushBuffer(byte[] b, int offset, int len)
			throws IOException {
		int bufferNum = pointer / BUFFER_SIZE;
		int bufferOffset = pointer % BUFFER_SIZE;
		int byteToCopy = Math.min(BUFFER_SIZE - bufferOffset, len);
		
		if(bufferNum == file.buffers.size()) {
			file.buffers.add(new byte[BUFFER_SIZE]);
		}
		
		byte[] buffer = file.getBuffer(bufferNum);
		System.arraycopy(b, offset, buffer, bufferOffset, byteToCopy);
		
		// left to be flush
		if(len > byteToCopy) {
			offset += byteToCopy;
			byteToCopy = len - byteToCopy;
			bufferNum++;
			if(bufferNum == file.buffers.size()) {
				file.buffers.add(new byte[BUFFER_SIZE]);
			}
			buffer = file.getBuffer(bufferNum);
			System.arraycopy(b, offset, buffer, 0, byteToCopy);
		}
		
		pointer += len;
		if(pointer > file.length)
			file.length = pointer;
		
		file.lastModify = System.currentTimeMillis();
	}
	
	/**
	 * reset this to an empty buffer
	 */
	public void reset() {
		try {
			seek(0);
		} catch(IOException e) {}
		file.length = 0;
	}

	@Override
	protected long length() throws IOException {
		return file.length;
	}
	
	public void seek(long pos) throws IOException {
		super.seek(pos);
		this.pointer = (int) pos;
	}
	
	

}
